package com.wk.springboot.scheduler;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wk.springboot.dispatch.MessageDispatcher;
import com.wk.springboot.entity.LocalMessage;
import com.wk.springboot.mapper.LocalMessageMapper;
import com.wk.springboot.retry.RetryStrategy;
import com.wk.springboot.service.MessageStoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.sql.Date;
import java.util.List;

import static com.wk.springboot.constant.CommonConstant.MessageConstant.FAILURE;
import static com.wk.springboot.constant.CommonConstant.MessageConstant.SUCCESS;

@Component
@Slf4j
public class MessageSenderScheduler {
    @Autowired
    private MessageDispatcher dispatcher;

    @Autowired
    private LocalMessageMapper localMessageMapper;

    @Autowired
    private RetryStrategy retryStrategy;

    // 异步消息处理（每5秒执行）
    @Scheduled(fixedRate = 5000)
    public void processAsyncMessages() {
        Page<LocalMessage> page = new Page<>(1, 100);
        List<LocalMessage> messages = localMessageMapper.selectPendingMessages(page);
        messages.forEach(msg -> {
            if (!retryStrategy.allowRetry(msg.getRetryCount())) {
                handleMaxRetriesExceeded(msg);
                return;
            }

            try {
                boolean success = dispatcher.dispatch(msg);
                if (success) {
                    msg.setStatus(SUCCESS);
                    localMessageMapper.updateById(msg);
                } else {
                    updateRetryInfoWithStrategy(msg);
                }
            } catch (Exception e) {
                updateRetryInfoWithStrategy(msg);
            }
        });
//        messages.forEach(msg -> {
//            boolean lockAcquired = tryLock(msg.getId());
//            if(lockAcquired) {
//                try {
//                    boolean success = dispatcher.dispatch(msg);
//                    if (!success) {
//                        // 更新消息状态为失败 计算下一次执行时间/重试次数
//                        msg.setCurrentRetryCount(msg.getCurrentRetryCount() + 1);
//
//                        localMessageMapper.updateStatus(msg.getId(), 3);
//                    }
//                    //下一次执行时间
//                    //执行次数
//                    //状态
//                    localMessageMapper.updateStatus(msg.getId(), success ? 2:3);
//                } finally {
//                    releaseLock(msg.getId());
//                }
//            }
//        });
    }

    private void updateRetryInfoWithStrategy(LocalMessage message) {
        Date nextRetryTime = retryStrategy.calculateNextRetryTime(
                message.getRetryCount() + 1,
                message.getNextRetryTime()
        );

        int updated = localMessageMapper.updateRetryInfo(
                message.getId(),
                message.getRetryCount() + 1,
                nextRetryTime,
                message.getVersion()
        );

        if (updated == 0) {
            log.warn("乐观锁更新失败 messageId:{}", message.getId());
        }
    }

    private void handleMaxRetriesExceeded(LocalMessage message) {
        localMessageMapper.updateStatus(message.getId(), FAILURE);
        // 触发告警或进入死信队列
        log.error("消息达到最大重试次数 messageId:{}, retryCount:{}",
                message.getId(), message.getRetryCount());
    }

    // 使用分布式锁保证并发安全
    private boolean tryLock(Long messageId) {
        // 实现基于Redis或数据库的锁
        return true;
    }

    private void releaseLock(Long messageId) {
        // 释放锁
    }
}